/**
 * @file smt.h
 *
 * @author mjsz (1349513606@qq.com)
 * @brief 步进电机驱动模块头文件
 * @version 0.1
 * @date 2025-05-23
 *
 * @copyright Copyright (c) 2025
 *
 */

#ifndef SMT_H
#define SMT_H
#ifdef __cplusplus
extern "C"
{
#endif

#include "public.h"

#define SMT_ERR_OK (0)
#define SMT_ERR_INVALID_OBJ (-1)   // 无效对象错误
#define SMT_ERR_INVALID_PARAM (-2) // 无效参数错误
#define SMT_ERR_NOT_IDLE (-3)      // 非空闲状态错误

#define SMT_EVT_CONFIG_DONE (0X1 << 0) // 配置完成事件
#define SMT_EVT_ORIGIN_OK (0X1 << 1)   // 回原点事件
#define SMT_EVT_SCRAM (0X1 << 2)       // 急停事件
#define SMT_EVT_MOTION_DONE (0X1 << 3) // 运动完成事件
#define SMT_EVT_NO_ORIGIN (0X1 << 4)   // 未找到原点事件

    struct smt;
    typedef void (*smt_evt_cb)(struct smt *obj, uint32_t evt);

    typedef struct smt_mechanical_params
    {
        uint16_t step_per_rev;     // 每转多少步
        float lead_steps;          // 导程(um/步)
        uint8_t div;               // 细分倍数
        uint32_t max_steps;        // 最大步数
        uint32_t out_origin_steps; // 出原点步数

    } _smt_mechanical_params, *smt_mechanical_params_t;

    typedef enum
    {
        SMT_OP_ORIGIN = 0, // 回原点
        SMT_OP_MOVE = 1,   // 移动
    } enum_smt_op_type_t;

    typedef struct smt_hw_info
    {
        uint16_t dir_pin;        // 方向引脚
        uint16_t step_pin;       // 步进引脚
        uint16_t enable_pin;     // 使能引脚
        uint16_t limit_pin;      // 限位引脚
        TIM_HandleTypeDef *htim; // 定时器句柄
        int pwm_chx;             // PWM通道号
        int pwm_chx_itr;         // PWM中断号
        uint16_t dir_lvl : 1;    // 正转
        uint16_t enable_lvl : 1; // 使能电平
        uint16_t limit_lvl : 1;  // 限位电平

    } _smt_hw_info, *smt_hw_info_t;

    typedef struct smt_motion_params
    {
        int velstart;       // 起始速度
        int velmax;         // 目标速度
        int velend;         // 最终速度
        uint32_t acc_steps; // 加速步数
        uint32_t dec_steps; // 减速步数
    } _smt_motion_params, *smt_motion_params_t;

    typedef struct smt_vel_curve
    {
        uint16_t *acc_tab;      // 加速度表
        uint16_t *dec_tab;      // 减速度表
        uint32_t acc_steps;     // 加速步数
        uint32_t dec_steps;     // 减速步数
        uint32_t uniform_steps; // 匀速步数
    } _smt_vel_curve, *smt_vel_curve_t;

    typedef enum
    {
        SMT_STATE_IDLE = 0,   // 空闲状态
        SMT_STATE_ACCELERATE, // 加速状态
        SMT_STATE_UNIFORM,    // 匀速状态
        SMT_STATE_DECELERATE, // 减速状态
        SMT_STATE_STOPPED,    // 停止状态
    } enum_smt_motion_state_t;
    typedef enum
    {
        SMT_DIR_FORWARD = 0, // 正转
        SMT_DIR_BACKWARD,    // 反转
    } enum_smt_dir_t;

    typedef enum
    {
        SMT_ORIGIN_FINGING, // 寻找原点
        SMT_ORIGIN_FINDED,  // 原点已找到
    } enum_smt_origin_state_t;

    typedef struct smt
    {
        uint8_t id;                           // 步进电机ID
        uint8_t div;                          // 细分倍数
        uint16_t step_per_rev;                // 步进电机每转多少步
        float lead_steps;                     // 导程(um/步)
        int cur_pos;                          // 当前位置
        int target_pos;                       // 目标位置
        enum_smt_origin_state_t origin_state; // 原点状态
        uint32_t origin_offset;               // 原点偏移量(步)
        enum_smt_motion_state_t curve_state;  // 运动曲线状态
        _smt_vel_curve vel_curve;             // 速度曲线参数
        enum_smt_dir_t dir;                   // 运动方向
        smt_hw_info_t hw;                     // 硬件信息
        smt_motion_params_t origin_vel_params; // 回原点速度曲线参数
        smt_motion_params_t target_vel_params; // 目标速度曲线参数
        _smt_mechanical_params mech_params;   // 机械参数
        enum_smt_op_type_t op_type;           // 操作类型
        smt_evt_cb evt_handler;               // 事件回调函数
    } _smt, *smt_t;

    void stm_vel_curve_cacl(smt_motion_params_t motion_params, smt_vel_curve_t curve, int target_pos); // 计算速度曲线

    int smt_back_origin(smt_t smt_obj, smt_evt_cb evt_handler);              // 回原点操作
    int smt_abs_move(smt_t smt_obj, int target_pos, smt_evt_cb evt_handler); // 绝对位置移动操作
    int smt_rel_move(smt_t smt_obj, int target_pos, smt_evt_cb evt_handler); // 相对位置移动操作
    int smt_stop(smt_t smt_obj);                                             // 停止操作
    inline int smt_is_idle(smt_t smt_obj)                                    // 等待空闲
    {
        return smt_obj->curve_state == SMT_STATE_IDLE ? 1 : 0;
    }
    inline int smt_get_pos(smt_t smt_obj) // 获取当前位置
    {
        return smt_obj->cur_pos;
    }

#ifdef __cplusplus
}
#endif

#endif